#include "umRingBuffer.h"
#include "umapi_libc.h"
typedef struct
{
	RingBuffer rb;
	UM_U8 * buff;
	UM_S32 buffSize, datalen, w, r, r0;
}RingBufferContext;

static UM_S32 sizeofRingBuffer(RingBuffer * p)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	return ptr->buffSize;
}
static UM_S32 getLengthRingBuffer(RingBuffer * p)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	return ptr->datalen;
}
static UM_VOID restRingBuffer(RingBuffer * p)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	ptr->datalen = ptr->w = ptr->r = 0;
}
static UM_VOID completeRingBuffer(RingBuffer * p)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	ptr->r = ptr->r0;
}
static UM_S32 readRingBuffer0(RingBuffer * p, UM_U8 * data, UM_S32 datalen)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	ptr->r0 = ptr->r;
	if(ptr->r0 < ptr->w && datalen <= ptr->w - ptr->r0)
	{
		umapi_memcpy(data, ptr->buff + ptr->r0, datalen);
		ptr->r0 += datalen;
		return datalen;
	}
	else if(ptr->r0 < ptr->w && ptr->w + (ptr->buffSize - ptr->r0) >= datalen)
	{
		UM_S32 len0 = ptr->buffSize - ptr->r0;
		umapi_memcpy(data, ptr->buff + ptr->r0, len0);
		umapi_memcpy(data + len0, ptr->buff, datalen - len0);
		ptr->r0 += datalen - len0;
		return datalen;
	}else
		return 0;
}
static UM_S32 readRingBuffer(RingBuffer * p, UM_U8 * data, UM_S32 datalen)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	if(ptr->r < ptr->w && datalen <= ptr->w - ptr->r)
	{
		umapi_memcpy(data, ptr->buff + ptr->r, datalen);
		ptr->r += datalen;
		ptr->datalen -= datalen;
		return datalen;
	}
	else if(ptr->r < ptr->w && ptr->w + (ptr->buffSize - ptr->r) >= datalen)
	{
		UM_S32 len0 = ptr->buffSize - ptr->r;
		umapi_memcpy(data, ptr->buff + ptr->r, len0);
		umapi_memcpy(data + len0, ptr->buff, datalen - len0);
		ptr->r += datalen - len0;
		ptr->datalen -= datalen;
		return datalen;
	}else
		return 0;
}
static UM_S32 writeRingBuffer(RingBuffer * p, UM_U8 * data, UM_S32 datalen)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	if(ptr->buffSize - ptr->w >= datalen)
	{
		umapi_memcpy(ptr->buff + ptr->w, data, datalen);
		ptr->w += datalen;
	}
	else
	{
		UM_S32 len0 = datalen - (ptr->buffSize - ptr->w);
		umapi_memcpy(ptr->buff + ptr->w, data, len0);
		umapi_memcpy(ptr->buff, data + len0, datalen - len0);
		ptr->w += datalen - len0;
	}
	ptr->datalen += datalen;
	return datalen;
}
RingBuffer * createRingBuffer(UM_S32 len)
{
	RingBufferContext *ptr = (RingBufferContext*)umapi_malloc(sizeof(RingBufferContext));
	ptr->buff = umapi_malloc(len);
	ptr->buffSize = len;
	ptr->datalen = 0;
	ptr->w = ptr->r = 0;
	ptr->rb.write = writeRingBuffer;
	ptr->rb.read = readRingBuffer;
	ptr->rb.getSize = sizeofRingBuffer;
	ptr->rb.getLength = getLengthRingBuffer;
	ptr->rb.rest = restRingBuffer;
	ptr->rb.read0 = readRingBuffer0;
	ptr->rb.complete = completeRingBuffer;
	return (RingBuffer *)ptr;
}
UM_VOID destoryRingBuffer(RingBuffer * p)
{
	RingBufferContext *ptr = (RingBufferContext*)p;
	umapi_free(ptr->buff);
	umapi_free(ptr);
}

